'''
Created on Aug 24, 2012

@author: Yonghui_Min
'''
import sys
import debug
import os
import re
class CHandle:
    def __init__(self, h):
        self._h = h
        self._count = 0
    
    def create(self):
        self._count += 1
        
    def close(self):
        self._count -= 1
        
    def get_count(self):
        return self._count
    
    def get_handle(self):
        return self._h
    
    def set_type(self,t):
        self._type = t
        
    def get_type(self):
        return self._type
    
    def set_stack(self,stack):
        self._stack = stack
        
    def get_stack(self):
        return self._stack

def parse_log_file(i,o):
    fi = open(i, 'r')
    fo = open(o, 'ab+')
    lines = fi.readlines()
    m = {0:CHandle(0)}
    pat_match_created = r'.* is created'
    pat_match_closed  = r'.* is closed'
    pat_find_created  = r'(.*) is created :(.*?) '
    pat_find_closed   = r'(.*) is closed '
    pat_match_handle_type = r'.*Type.*'
    pat_match_stack = r'.*ChildEBP.*'
    to_process = False
    stack = []
    
    
    
    for line in lines:
        
        # match created
        if re.match(pat_match_created, line):
            s = re.findall(pat_find_created, line)
            
            if s == []:
                continue
            
            debug.output('handle created', s)
            (k,t) = s[0]
            
            if m.has_key(k):    
                v = m[k]
                if v.get_count() == 0:
                    v.create()
                    v.set_type(t)
                    v.set_stack(stack)
            else:
                v = CHandle(k)
                v.create()
                v.set_stack(stack)
                v.set_type(t)
                m[k] = v
                
            stack = []
                
        # match closed
        elif re.match(pat_match_closed, line):
            s = re.findall(pat_find_closed, line)
            
            if s == []:
                continue
            
            debug.output('handle closed', s)
            k = s[0]
            
            if to_process != True:
                continue
            
            if m.has_key(k):
                v = m[k]
                if v.get_count() == 1 :
                    v.close()

        # check type of handle to be closed
        elif re.match(pat_match_handle_type, line):
            if line.find('Event') != -1 or line.find('Thread') != -1: #or line.find('Mutex') != -1:
                to_process = True
            else:
                to_process = False
        # normal
        else:
            
            # stack info
            if re.match(pat_match_stack, line):
                stack = []
            stack.append(line)
                
    count = 0          
    for k in m:
        v = m[k]
        if v.get_count() > 0:
            count += 1
            #print v.get_stack()
            fo.write('======================================================================================\n')
            fo.writelines(v.get_stack())
            s ='%s (%s): %d\n' % (v.get_handle(),v.get_type(), v.get_count())
            fo.write(s)
            fo.write('======================================================================================\n')
    
    final = 'leak count = %d\n' % count
    print final
    fo.write(final)
            
    fi.close()
    fo.close()
            

def main():
    # parse command line
    argv = sys.argv
    debug.output('argv  :', argv)
    argc = len(argv)
    debug.output('argc  :', argc)
    
    if argc != 3:
        debug.output('error :','usage : main -i [log file]')
    else:
        i  = argv[1]
        o  = argv[2]
        
        if os.path.isfile(i):
            parse_log_file(i,o)
        else:
            debug.output('error :', 'invalid log file')


if __name__ == '__main__':
    main()